
var mediaRecorder   = null 
var mediaStream     = null 
const camera_vidpid = '1bd0:28c5' // 正式设备: '1bd0:28c5'  , 测试设备: '1bcf:2281'
// const camera_vidpid = '1bcf:2281'


/* 流程:
 * 1. 注册H5端录制视频代理, window.api?.setH5VideoRecordImpl(), 供 Node 调用;
 * 2. 发起录制视频: window.api?.startVideoRecord() 
 *    (1) 通知Node创建视频文件句柄, 等待H5视频流传过来写入
 *    (2) 执行代理在H5进行实际的视频录制操作
 */

console.log('[videoRecordH5] 注册录像事件')

// 注册H5端录制视频代理, 供 Node 调用


function init() {
  console.log('[videoRecordH5] init ...')
  window.api?.setH5VideoRecordImpl( (event, arg)=>{
    if (event.type === 'start') {
      return _startVideoRecord() 
      
    } else if (event.type === 'stop') {
      return _stopVideoRecord()
      
    } else if (event.type === 'get-format') {
      return JSON.stringify( _getFormat() )
      
    } 
  })
}


function _startVideoRecord() {
  return new Promise(async resolve =>{ 
    // 1.查找摄像头 
    let cameraDevId = await _findCamera(camera_vidpid) 
    console.log('[videoRecord] _startVideoRecord cameraDevId ', cameraDevId) 
    
    if (!cameraDevId) {
      console.log('[videoRecord] 找不到摄像头: ', camera_vidpid)
      resolve(JSON.stringify({ code: 400, message: '请插入摄像头', data: null})) 
      return 
    }
    
    // 2. 取流 
    try {
      mediaStream = await navigator.mediaDevices.getUserMedia({ 
        audio: true, 
        video: { 
          width: 1280, 
          height: 720, 
          transform: 'scaleX(-1)', 
          deviceId: { exact: cameraDevId },
        },
      }) 
      if (!mediaStream) {
        resolve(JSON.stringify({ code: 401, message: '找不到摄像头', data: null})) 
        return 
      }
      // 3. 开始录制
      let ret = _initMediaRecorder(async (chunk)=>{
        window.api?.writeVideoChunk(chunk, (res)=>{
          
        })
      })
      
      resolve(JSON.stringify(ret))
      
    } catch(err) { 
      console.log('[videoRecord] startVideoRecord get camera fail:') 
      console.error(err) 
      let tips = err.message == 'Device in use' ? '摄像头被占用' : '摄像头打开失败' 
      resolve(JSON.stringify({ code: 402, message: tips, data: null }))
    } 
    
  }) 
} 

function _stopVideoRecord() {
  console.log('[videoRecord] stopVideoRecord')
  if (mediaRecorder) {
    mediaRecorder.stop() 
    mediaRecorder = null 
  }
  if (mediaStream) {
    mediaStream.getTracks().forEach(t => t.stop()) 
    mediaStream = null
  }
  return Promise.resolve(JSON.stringify({code:200, message: 'success', data: null})) 
}

// 查找摄像头: vidpid 格式: '1bd0:28c5' 
function _findCamera(vidpid) {
  return new Promise(resolve => {
    navigator.mediaDevices.enumerateDevices()
    .then((res) => {
      const cameras = res.filter((device) => device.kind === 'videoinput')
      const cur_camera = cameras.find((device) => {
        console.log('[videoRecordH5] camera ---', device.label)
        return device.label.toLowerCase().includes(vidpid)
      })
      console.log('[videoRecord] _findCamera find camera: ', vidpid,  cur_camera != null) 
      resolve(cur_camera?.deviceId) 
    })
    .catch(err=>{
      console.log('[videoRecord] initCamera find camera error:')
      console.log(err) 
      resolve(null) 
    })
  })
}

function _initMediaRecorder(chunkCallback) {  

  let format  = _getFormat()
  let options = { 
    mimeType: format.mimeType,
    videoBitsPerSecond: 1024 * 1024 * 4
  }
  
  try {
    mediaRecorder = new MediaRecorder(mediaStream, options)
    mediaRecorder.ondataavailable = async (event) => {
      if (event.data && event.data.size > 0) {
        // 将数据转换为 ArrayBuffer 以便通过 IPC 发送 
        const arrayBuffer = await event.data.arrayBuffer()
        if (chunkCallback) chunkCallback(arrayBuffer) 
      }
    }
    mediaRecorder.onstop = () => {
      console.log('[videoRecord] onstop') 
      // 释放摄像头
      if (mediaStream) {
        mediaStream.getTracks().forEach(t => t.stop()) 
        mediaStream = null
      }
    }
    mediaRecorder.start(1000)  // 每1秒生成一个块
    
    return {code: 200, message: '获取摄像头成功', data: { format: format.extName }} 
    
  } catch (err) {
    console.log('[videoRecord] initMediaRecorder error:', JSON.stringify(err)) 
    return {code: 406, message: '获取摄像头失败', data: { format: format.extName }} 
  }
  
}

function _getFormat() {
  let supportWebm = MediaRecorder.isTypeSupported('video/webm; codecs=vp9,opus')
  let supportMp4  = MediaRecorder.isTypeSupported('video/mp4; codecs=avc1.640028,mp4a.40.2')
  let extName     = supportMp4 ? '.mp4' : '.webm'
  let mimeType    = supportMp4 ? 'video/mp4; codecs=avc1.640028,mp4a.40.2' : 'video/webm; codecs=vp9,opus' 
  console.log(`[videoRecord], support webm: ${supportWebm}, mp4: ${supportMp4}`) 
  return {extName, mimeType} 
}

function getStream() {
  return mediaStream 
}

module.exports = {
  init,
  getStream,
}
